﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows.Forms;
using System.IO;
using Delta.Forms;
using IntegrationExample.Logic;
using Microsoft.Win32;
using System.Data.SqlServerCe;

namespace IntegrationExample
{
    public partial class MainForm : Form
    {
        /// <summary>
        /// Функция, определяющая наличие дочерних узлов
        /// </summary>
        private Func<object, bool> HasChildrenNodes;

        /// <summary>
        /// Название файла для WinRAR
        /// </summary>
        private string WinRarFileName;

        /// <summary>
        /// Текущая директория
        /// </summary>
        private string currentDirectory;

        public MainForm()
        {
            InitializeComponent();
            
            //Нахождение WinRAR в реестре
            RegistryKey key = Registry.ClassesRoot.OpenSubKey(@"WinRAR\shell\open\command");
            if (key != null)
            {
                string str = key.GetValue("").ToString();
                //Путь к WinRAR
                WinRarFileName = str.Split('"')[1];
            }
            else
            {
                MessageBox.Show("Невозможно архивировать и разархивировать файлы", "WinRAR не установлен", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }

            HasChildrenNodes = x =>
                {
                    DirectoryInfo di;
                    if (x is DriveInfo)
                    {
                        di = new DirectoryInfo((x as DriveInfo).Name);
                    }
                    else if (x is DirectoryInfo)
                    {
                        di = x as DirectoryInfo;
                    }
                    else
                    {
                        return false;
                    }
                    return di.GetDirectories().Length > 0;
                };
            FillTree();
        }

        /// <summary>
        /// Заполнение дерева каталогов (дисков) в treeView
        /// </summary>
        public void FillTree()
        {
            List<string> drives = new List<string>(Directory.GetLogicalDrives());
            DriveInfo di;
            TreeNode node;
            trvCatalog.ImageList = new ImageList();

            trvCatalog.ImageList.ColorDepth = ColorDepth.Depth32Bit;
            trvCatalog.BeginUpdate();
            trvCatalog.Nodes.Clear();

            drives.ForEach(x =>
            {
                try
                {
                    di = new DriveInfo(x);
                    if (!di.IsReady)
                        return;

                    trvCatalog.ImageList.Images.Add(ForWinAPI.GetSystemIcon(di.Name));
                    node = new TreeNode(string.Format("{0} ({1})", di.VolumeLabel, di.Name.TrimEnd('\\')));
                    node.ImageIndex = trvCatalog.ImageList.Images.Count - 1;
                    node.Tag = new DirectoryInfo(x);

                    if (HasChildrenNodes(di))
                    {
                        node.Nodes.Add(string.Empty);
                    }
                    node.ImageIndex = trvCatalog.ImageList.Images.Count - 1;
                    trvCatalog.Nodes.Add(node);
                }
                catch
                {
                    ;
                }
            });

            trvCatalog.EndUpdate();
        }

        private void trvCatalog_AfterCollapse(object sender, TreeViewEventArgs e)
        {
            e.Node.Nodes.Clear();
            e.Node.Nodes.Add(string.Empty);
        }

        /// <summary>
        /// Выбор одного из каталогов
        /// </summary>
        private void trvCatalog_BeforeSelect(object sender, TreeViewCancelEventArgs e)
        {
            lvFiles.Clear();
            e.Node.SelectedImageIndex = e.Node.ImageIndex;
            lvFiles.SmallImageList = new ImageList();
            lblPath.Text = ((DirectoryInfo)e.Node.Tag).FullName;
            AddInListView((DirectoryInfo)e.Node.Tag);
        }

        /// <summary>
        /// Раскрытие одного из каталогов
        /// </summary>
        private void trvCatalog_BeforeExpand(object sender, TreeViewCancelEventArgs e)
        {
            e.Node.Nodes.Clear();
            e.Node.TreeView.BeginUpdate();

            TreeNode node = e.Node;

            if (node == null)
                return;
            string dirPath = (node.Tag as DirectoryInfo).FullName;
            DirectoryInfo di = new DirectoryInfo(dirPath);
            lblPath.Text = di.FullName;
            AddInListView(di);

            TreeNode child;
            currentDirectory = di.FullName;
            di.GetDirectories().ToList().ForEach(x =>
            {
                try
                {
                    child = new TreeNode(x.Name);
                    trvCatalog.ImageList.Images.Add(ForWinAPI.GetSystemIcon(x.FullName));
                    child.Tag = x;
                    if (HasChildrenNodes(x))
                    {
                        child.Nodes.Add(string.Empty);
                    }

                    e.Node.Nodes.Add(child);
                    int count = e.Node.Nodes.Count - 1;
                    int count2 = trvCatalog.ImageList.Images.Count - 1;
                    e.Node.Nodes[count].ImageIndex = count2;
                }
                catch
                {
                    ;
                }
            });
            trvCatalog.EndUpdate();
        }

        /// <summary>
        /// Добавление файлов в listView
        /// </summary>
        /// <param name="di"></param>
        private void AddInListView(DirectoryInfo di)
        {
            lvFiles.Clear();
            lvFiles.SmallImageList = new ImageList();
            currentDirectory = di.FullName;
            di.GetFiles().ToList().ForEach(x =>
            {
                try
                {
                    lvFiles.SmallImageList.Images.Add(ForWinAPI.GetSystemIcon(x.FullName));
                    
                    lvFiles.Items.Add(x.Name);
                    int count = lvFiles.Items.Count;
                    int count2 = lvFiles.SmallImageList.Images.Count;
                    lvFiles.Items[count - 1].ImageIndex = count2 - 1;
                    lvFiles.Items[count - 1].Tag = (object)x;
                }
                catch
                {
                    ;
                }
            });
        }

        private void lvFiles_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Right)
            {
                if (WinRarFileName != null)
                {
                    cmsFileAction.Items[0].Enabled = true;
                    cmsFileAction.Items[1].Enabled = true;
                }
                cmsFileAction.Items[2].Enabled = false;
                cmsFileAction.Items[3].Enabled = true;
                cmsFileAction.Show((Control)sender, e.X, e.Y);
            }
        }

        private void lvFiles_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Right)
            {
                cmsFileAction.Items[0].Enabled = false;
                cmsFileAction.Items[1].Enabled = false;
                cmsFileAction.Items[2].Enabled = true;
                cmsFileAction.Items[3].Enabled = false;
                cmsFileAction.Show((Control)sender, e.X, e.Y);
            }
        }

        /// <summary>
        /// Запуск *.exe или начало работы с БД
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void lvFiles_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            List<string> liFileName = new List<string>();

            foreach (var c in lvFiles.SelectedItems)
            {
                string _filename = ((FileInfo)(((ListViewItem)c).Tag)).FullName;

                if (_filename.IndexOf(".exe") >= 0)
                {
                    liFileName.Add(_filename);
                    Process proc = new Process();
                    proc.StartInfo.FileName = _filename;
                    proc.Start();
                }
                if (_filename.IndexOf(".sdf") > 0)
                {
                    ForDataBases fdb = new ForDataBases("Data Source='" + _filename + "';");
                    fdb.ShowDialog();
                }
            }
        }

        /// <summary>
        /// Архивирование
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void archiveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Process proc = new Process();
            proc.StartInfo.FileName = WinRarFileName;
            string filename = ((lvFiles.SelectedItems[0].Tag) as FileInfo).FullName;
            string filenameArchive = filename.Replace(Path.GetExtension(filename), ".rar");

            proc.StartInfo.Arguments = " a \"" + filenameArchive + "\"" + " \"" + filename + "\"";
            
            proc.Start();
            while (!proc.HasExited)
                ;
            AddInListView(new DirectoryInfo(Path.GetDirectoryName(filenameArchive)));
        }

        /// <summary>
        /// Разархивирование
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void unarchiveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Process proc = new Process();
            proc.StartInfo.FileName = WinRarFileName;
            string filenameArchive = ((lvFiles.SelectedItems[0].Tag) as FileInfo).FullName;

            proc.StartInfo.Arguments = " x \"" + filenameArchive.Replace(".rar", "") + "\" *.* " + Path.GetDirectoryName(filenameArchive);

            proc.Start();
            while (!proc.HasExited)
                ;
            AddInListView(new DirectoryInfo(Path.GetDirectoryName(filenameArchive)));
        }

        /// <summary>
        /// Создание БД
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void createDBToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string nameDB = "";
            try
            {
                InputBoxForm.Query("Введите имя базы данных", "Имя БД", ref nameDB);
                string connString = "Data Source='" + currentDirectory + "\\" + nameDB + ".sdf';";
                SqlCeEngine sqlCeEngine = new SqlCeEngine(connString);
                sqlCeEngine.CreateDatabase();
            }
            catch (Exception)
            {
                MessageBox.Show("Ошибка при создании БД.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                AddInListView(new DirectoryInfo(currentDirectory));
            }
        }

        /// <summary>
        /// Удаление файла
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void deleteFileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                string fileName = ((lvFiles.SelectedItems[0].Tag) as FileInfo).FullName;
                File.Delete(fileName);
            }
            catch (Exception)
            {
                MessageBox.Show("Файл не выбран", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                AddInListView(new DirectoryInfo(currentDirectory));
            }

        }
    }
}